import React, { PureComponent } from 'react';
import ModalItem from '../ModalItem';
import { loadScript,isObjectValEqual } from 'jh-utils'
import InputComp from '../InputComp'
import { AimOutlined } from '@ant-design/icons';
import styles from './index.module.less'
import { Input,Empty,Tag } from "antd";
import * as lbsConfig from './lbsConfig'
import {cloneDeep, filter, isEmpty, isFunction, map, omit, pick,find} from "lodash-es";
import CardPane  from "./CardPane";
import classNames from 'classnames';
import BaseField from "../Base/BaseField";
const { Search } = Input;

const rspCallback = (rsp)=>{
    if(rsp&&rsp.status == 200){
        return rsp.data||null
    }
    return null;
};

const markStyle = lbsConfig.markStyle;
const markStyKey = lbsConfig.markStyleKey;
const customMarkId  = lbsConfig.customMarkId;
/**
 * 坐标拾取器
 */
export default class LocationBox extends BaseField{

    /**
     * 获取地址信息
     */
    fetchSearchAddress(){
        let ajaxData = {
            key:this.props.mapKey,
            page_size:20
        };
        if(this.ad_info){
            ajaxData['boundary'] = `region(${this.ad_info.city},0)`;
        }
        if(!isEmpty(this.searchData)){
            ajaxData['keyword'] = encodeURI(this.searchData['keyword']);
        }

        return  this.reqGet(lbsConfig.lbsApi.search,ajaxData,{
            jsonp:'callback',
            jsonpCallback:'QQmap'
        }).then(rspCallback).then(mapRsp=>{
            let addrList = [];
            if(mapRsp&&0 === mapRsp['status']){
                addrList = mapRsp.data||[];
            }
            this.setState({
                addrList
            },()=>{
                this.setMapMark();
            });
            return mapRsp;
        });

    }

    /**
     * 根据IP地址获取当前经纬度位置
     */
    fetchCurrLocation(){
        let $this = this;
        return  this.reqGet(lbsConfig.lbsApi.loctionByIp,{
            key:this.props.mapKey
        }).then(rspCallback).then(mapRsp=>{
            if(mapRsp&&mapRsp.status===0){
                const { ad_info,location} = mapRsp.result;
                $this.ad_info = ad_info;
                $this.setMapOptValue('location',location);
            }
            return mapRsp;
        });
    }

    /**
     * 获取省市区信息
     */
    fetchArea(){
        return  this.reqGet(lbsConfig.lbsApi.citys,{
            key:this.props.mapKey
        }).then(rspCallback).then(mapRsp=>{
            let newList = [];
            if(mapRsp&&mapRsp.status===0){
                let pList = mapRsp.result?mapRsp.result[0]:[];
                let cList = mapRsp.result?mapRsp.result[1]:[];
                let directly = ['北京','上海','天津','重庆'],directlyChild = [];
                newList = map(pList,o=>{
                    if(-1 < directly.indexOf(o.name)){ directlyChild.push(o);return {}; }
                    let childKey = `${o.id.substring(0,2)}`;
                    let child = filter(cList,o=>o.id.substring(0,2) === childKey);
                    return {
                        ...o,
                        children:child
                    }
                }).filter(o=>!isEmpty(o));
                newList.unshift({
                    name:'直辖市',
                    id:'00000001',
                    children:directlyChild
                });
                this.setState({
                    areaList:newList
                });
            }
            return mapRsp;
        })
    }


    /**
     * 经纬度、地址之间转换
     * @param data {location:{lat,lng}}\{address:...}
     * @returns {boolean}
     */
    fetchGeocoder(data){
        let ajaxData = {
            key:this.props.mapKey
        };
        if(data.hasOwnProperty('location')&&!isEmpty(data.location)){
            ajaxData['location'] = `${data.location.lat},${data.location.lng}`;
        }else if(data.hasOwnProperty('address')&&!isEmpty(data.address)){
            ajaxData['address'] = data['address'];
        }else{
            return false;
        }
        return  this.reqGet(lbsConfig.lbsApi.geocoder,ajaxData).then(rspCallback).then(mapRsp=>{
            if(mapRsp&&mapRsp.status===0){
                let result = mapRsp.result;
                if(data.hasOwnProperty('location')&&!isEmpty(result)){
                    const { location } = result;
                    let address = result.address_component;
                    this.setSelectedAddr({
                        location,
                        address:`${address.province||''}${address.city||''}${address.district||''}${address.street||''}${address.street_number||''}`
                    })
                }
            }
            return mapRsp;
        })
    }

    // fetchGeoLocation(){}
    // fetchGeoAddress(){}


    static defaultProps = {
        mapKey:lbsConfig.mapKey,
        options:{}
    };


    constructor(props) {
        super(props);
        this.ad_info = {};
        this.searchData = {};
        this.defaultGeome = [];
    }

    initState(props) {
        return {
            ...super.initState(props),
            showModal:false,
            showArea:false,//选择城市弹框
            addrList:[],//搜索地址
            areaList:[],//选择城市
            selectedAddr:null,//选中的地址；选地址列表、地图
            mapOptions:{
                zoom:10,
                ...props.options
            },
        };
    }

    mapCompRef = null;

    tempMarkList = [];


    _init(){
        const { value } = this.state;
        if(!isEmpty(value)&&value.hasOwnProperty('lat')&&value.hasOwnProperty('lng')){
            this.fetchGeocoder({
                location:{...value}
            }).then(mapRsp=>{
                if(mapRsp&&mapRsp.status===0){
                    const { location,address,ad_info } = mapRsp.result;
                    this.ad_info = ad_info;
                    this.defaultGeome = [{
                        id:customMarkId.INIT_VALUE_MAP_LAT_LNG_ID,
                        styleId:markStyKey.init,
                        location
                    }];
                    this.setMapOptValue('location',location);
                    this.setState({
                        selectedAddr:{
                            location,
                            address:value.desc?value.desc:address
                        }
                    });
                }
            });
        }else{
            this.fetchCurrLocation();
        }
        this.fetchArea();
    }


    get locationText(){
        const { value } = this.state;
        return !isEmpty(value)?`${value.lat},${value.lng}`:'';
    }



    /**
     * 选择地址
     * @returns {null}
     */
    setSelectedAddr(value){
        /**
         * 如果选的是地址列表
         */
        if(value.hasOwnProperty('id')){
            //清空选经纬度的mark标识
            if(this.mapCompRef&&isFunction(this.mapCompRef.getMarkGeometryById)){
                let geometry = this.mapCompRef.getMarkGeometryById(customMarkId.CLICK_MAP_LAT_LNG_ID);
                if(geometry){
                    this.deleteMarkerLayer([customMarkId.CLICK_MAP_LAT_LNG_ID]);
                }
            }
            //设置选择地址列表的mark标识
            this.setMapMark(value);
            //重置地图中心点
            if(value.hasOwnProperty('location')&&!isEmpty(value.location)){
                this.setMapOptValue('location',value.location);
            }
        }
        this.setState({
            selectedAddr:value||null
        });
    }

    /**
     * 设置地图的marker标记
     * @param curMark 选中的地址
     */
    setMapMark(curMark = {}){
        const { addrList } = this.state;
        if(this.mapCompRef){
            if(!isEmpty(addrList)){
                this.tempMarkList = map(cloneDeep(addrList),o=>{
                    let newObj = {
                        ...pick(o,['id','location']),
                        styleId:markStyKey.def
                    };
                    if(!isEmpty(curMark)&&(curMark.hasOwnProperty('id')&&curMark.id === o.id)){
                        newObj['styleId'] = markStyKey.act;
                    }
                    return newObj;
                });
                isFunction(this.mapCompRef.updateMarkerLayer)&&this.mapCompRef.updateMarkerLayer(this.tempMarkList);
            }else{
                this.tempMarkList = [];
                this.clearMarkerLayer();
            }
        }
    }

    /**
     * 清空地图标识
     */
    clearMarkerLayer(){
        isFunction(this.mapCompRef.clearMarkerLayer)&&this.mapCompRef.clearMarkerLayer();
    }

    deleteMarkerLayer(ids){
        isFunction(this.mapCompRef.deleteMarkerLayer)&&this.mapCompRef.deleteMarkerLayer(ids);
    }


    /**
     * 选中地址列表
     * @param value
     */
    handleClickAddr(value){
        this.setSelectedAddr(value)
    }

    /**
     * 点击地图
     * @param value
     */
    handleClickMap(value){
        let location = value;

        //标识选中的位置
        let newList = [{
            id:customMarkId.CLICK_MAP_LAT_LNG_ID,
            location,
            styleId:markStyKey.act
        }];
        if(!isEmpty(this.tempMarkList)){
            let tObj = find(this.tempMarkList,o=>o.styleId === markStyKey.act);
            if(tObj){
                let reObj = {...tObj,styleId:markStyKey.def}
                newList.push(reObj);
            }
        }
        isFunction(this.mapCompRef.updateMarkerLayer)&&this.mapCompRef.updateMarkerLayer(newList);
        this.fetchGeocoder({
            location
        })
    }

    /**
     * 选择城市
     * @param value
     */
    handleCity(value){
        if(!isEmpty(value)){
            this.ad_info = {
                ...omit(value,['location']),
                city:value.name
            };
            this.setMapOptValue('location',value.location,()=>{
                //重置缩放级别
                let zoom = 10;
                this.setMapOptValue('zoom',zoom,()=>{
                    isFunction(this.mapCompRef.setZoom)&&this.mapCompRef.setZoom(zoom);
                    this.clearMarkerLayer();
                })
            });
            this.areaToggle();
        }
    }


    /**
     * 搜索地址信息
     * @param keyword
     */
    onSearch(keyword){
        // this.clearMarkerLayer();
        let markIds = map(this.tempMarkList,o=>{
            return o.id;
        });
        if(markIds){
            this.deleteMarkerLayer(markIds);
        }
        this.searchData = {
            ...this.searchData,
            keyword
        };
        this.fetchSearchAddress();
    }

    setMapZoom(value){
        this.setMapOptValue('zoom',value);
    }

    /**
     *
     * @param oKey
     * @param value
     * @param cb
     */
    setMapOptValue(oKey,value,cb){
        const { mapOptions } = this.state;
        this.setState({
            mapOptions:{
                ...mapOptions,
                [oKey]:value
            }
        },()=>{
            isFunction(cb)&&cb();
        });
    }

    /**
     *open\close Modal
     * */
    toggle = ()=>{
        if(this.state.showModal===false){
            this._init();
        }
        this.setState({
            showModal:!this.state.showModal
        });
    };

    /**
     *open\close areaModal
     * */
    areaToggle = ()=>{
        this.setState({
            showArea:!this.state.showArea
        });
    }

    onCancel(){
        this.toggle();
    }

    onConfirm(e){
        if(!isEmpty(this.state.selectedAddr)){
            let value = {...this.state.selectedAddr};
            this.hdlValueChange({...value.location,desc:value['address']})
        }
        this.toggle();
    }

    mainRender(){
        const { showModal,addrList,selectedAddr,mapOptions,areaList,showArea } = this.state;
        let areaClass = classNames(styles['area-pane']);
        if(showArea){
            areaClass = classNames(styles['area-pane'],styles['open']);
        }
        return (
            <>
                <InputComp  value={this.locationText}
                            disabled={true}
                            addonAfter={<span onClick={this.toggle}
                                              className={styles['selAddr']}><AimOutlined /></span>}/>
                <ModalItem visible={showModal}
                           closable={false}
                           width={650}
                           bodyStyle={{padding:'0px'}}
                           cancelText={'取消'}
                           okText={'确认'}
                           onOk={this.onConfirm.bind(this)}
                           onCancel={this.onCancel.bind(this)}>
                    <div className={styles['map-box']}>
                        <div className={styles['map-box-head']}>
                            <div className={styles['map-search']}>
                                <Search placeholder="请输入地址"
                                        onSearch={this.onSearch.bind(this)}
                                        style={{width:230}}
                                        enterButton="搜索"/>
                            </div>
                            <div className={styles['map-info']}>
                                <p>
                                    <label>
                                        <strong>选中坐标:</strong><label style={{marginLeft:'5px'}}>{selectedAddr&&selectedAddr.location?<Tag color="#2db7f5">{`${selectedAddr.location.lat},${selectedAddr.location.lng}`}</Tag>:'请选择...'}</label>
                                    </label>
                                </p>
                                <p>
                                    <label>
                                        <strong>选中地址:</strong><label style={{marginLeft:'5px'}}>{selectedAddr&&selectedAddr.address?<Tag color="#2db7f5">{`${selectedAddr.address}`}</Tag>:'请选择...'}</label>
                                    </label>
                                </p>
                            </div>
                        </div>
                        <div className={styles['map-box-body']}>
                            <div className={styles['map-box-tabar']}>
                                <label>{this.ad_info?this.ad_info.city:'-'}</label><span className={styles['switch-city']} onClick={this.areaToggle.bind(this)} style={{padding:'0 10px',color:'#fff'}}>[更换城市]</span><label>当前缩放级别:{mapOptions.zoom}</label>

                                {
                                    !isEmpty(areaList)&&<div className={areaClass}>
                                        <h3>全国城市</h3>
                                        <div className={styles['area-pane-body']}>
                                            {
                                                !isEmpty(areaList)?map(areaList,o=>{
                                                    return (
                                                        <div key={o.id} className={styles['area-pane-body-row']}>
                                                            <div className={styles['area-pane-body-col-label']}>{o.name||''}</div>
                                                            <div className={styles['area-pane-body-col-item']}>
                                                                {
                                                                    !isEmpty(o.children)&&map(o.children,city=>{
                                                                        return (
                                                                            <span onClick={this.handleCity.bind(this,city)} key={city.id}>{city.name||''}</span>
                                                                        )
                                                                    })
                                                                }
                                                            </div>
                                                        </div>
                                                    )
                                                }):<Empty/>
                                            }
                                        </div>
                                    </div>
                                }


                            </div>
                            <div className={styles['map-box-box-container']}>
                                <div className={styles['map-address']}>
                                    {
                                        !isEmpty(addrList)?map(addrList,(item)=>{
                                            return (
                                                <CardPane key={item.id} handleClickSite={this.handleClickAddr.bind(this)}
                                                          curSite={selectedAddr}
                                                          item={item}/>
                                            );
                                        }):<div className={styles.empty}><Empty/></div>
                                    }
                                </div>
                                <div className={styles['map-content']}>
                                    <MapComp {...this.props}
                                             onRef={(ref)=>{
                                                 this.mapCompRef = ref;
                                             }}
                                             options={mapOptions}
                                             markerOptions={{
                                                 styles:markStyle,
                                                 geometries:this.defaultGeome
                                             }}
                                             handleZoom={this.setMapZoom.bind(this)}
                                             handleClickMap={this.handleClickMap.bind(this)}/>
                                </div>
                            </div>
                        </div>
                    </div>
                </ModalItem>
            </>
        )
    }
}

/**
 * map地图
 */
class MapComp extends PureComponent{

    static defaultProps = {
        mapStyle:{},
        markerOptions:{}
    };

    constructor(props) {
        super(props);
        this.state = {
            showModal:false
        };
    }

    mapObj = null;

    markerLayer = null;

    componentDidMount(){
        isFunction(this.props.onRef)&&this.props.onRef(this);
    }

    _initMap(){
        let $this = this;
        loadScript(`https://map.qq.com/api/gljs?v=1.exp&key=${this.props.mapKey}`,()=>{
            $this.init();
        });
    }

    componentDidUpdate(prevProps, prevState, snapshot){
        if(!isObjectValEqual(prevProps.options.location, this.props.options.location)){
            if(this.props.options.location){
                // this.setMapCenter(this.props.options.location)
                if(isEmpty(this.mapObj)){
                    this._initMap();
                }else{
                    this.setMapCenter(this.props.options.location)
                }
            }
        }
    }

    /**
     * 初始化
     * @returns {boolean}
     */
    init(){
        let $this = this;
        if(TMap){
            const { options,handleClickMap,handleZoom,markerOptions } = this.props;
            let container = document.getElementById('container');
            if(isEmpty(options.location)){
                return false;
            }
            let center = new TMap.LatLng(options.location.lat, options.location.lng);
            let newOptions = {...omit(options,['center'])};
            this.mapObj = new TMap.Map(container,{
                center,
                // showControl:false,
                // draggableCursor:'crosshair',
                viewMode:'2D',
                ...newOptions
            });

            //绑定点击事件
            this.mapObj.on("click",function(evt){
                let lat = evt.latLng.getLat().toFixed(6);
                let lng = evt.latLng.getLng().toFixed(6);

                isFunction(handleClickMap)&&handleClickMap({
                    lat,
                    lng
                })
            });

            //鼠标移动事件
            this.mapObj.on("mousemove",function(evt){
                let lat = evt.latLng.getLat().toFixed(6);
                let lng = evt.latLng.getLng().toFixed(6);
            });

            //缩放事件
            this.mapObj.on('zoomend',function(evt){
                if($this.mapObj){
                    let zoom = $this.mapObj.getZoom();
                    isFunction(handleZoom)&&handleZoom(Math.ceil(zoom));
                }
            });

            //markerLayer配置
            let newStyles = {};
            if(markerOptions.hasOwnProperty('styles')){
                for(let styleKey in markerOptions['styles']){
                    let tObj = markerOptions['styles'][styleKey];
                    if(!isEmpty(tObj)){
                        newStyles[styleKey] = new TMap.MarkerStyle({
                            ...tObj
                        });
                    }
                }
            }

            if(markerOptions.hasOwnProperty('geometries')){
                let newGeometries = cloneDeep(markerOptions['geometries']);
                markerOptions['geometries'] = this.getNewGeometries(newGeometries);
            }
            this.markerLayer = new TMap.MultiMarker({
                map:this.mapObj,
                ...omit(markerOptions,['map','style']),
                styles:newStyles
            });

            this.markerLayer.on('click',(e)=>{
                console.log('markerLayer evt');
            });
        }
    };

    /**
     * 修改中心位置
     * @param location
     */
    setMapCenter(location){
        if(!isEmpty(this.mapObj)&&TMap&&!isEmpty(location)){
            let center = new TMap.LatLng(location.lat, location.lng);
            this.mapObj.setCenter(center);
        }
    }

    /**
     * 修改地图缩放
     * @param value
     */
    setZoom(value){
        if(!isEmpty(this.mapObj)){
            this.mapObj.setZoom(value);
        }
    }

    getMarkGeometryById(id){
        let pointGeometry = {}
        if(this.markerLayer){
            pointGeometry =  this.markerLayer.getGeometryById(id);
        }
        return pointGeometry;
    }

    /**
     * 在点记图层中新增标记
     * @param geometries [{
        "id": "1",   //点标记唯一标识，后续如果有删除、修改位置等操作，都需要此id
        "styleId": 'myStyle',  //指定样式id
        "position": new TMap.LatLng(39.954104, 116.357503),  //点标记坐标位置
        "properties": {//自定义属性
            "title": "marker1"
        }]
     */
    addMarkerLayer(geometries = []){
        if(this.markerLayer&&!isEmpty(geometries)&&TMap){
            this.markerLayer.add(this.getNewGeometries(geometries));
        }
    }

    /**
     *
     * @param geometries
     * @returns {Array|*[]}
     */
    getNewGeometries(geometries){
        return map(geometries,o=>{
            let position = {};
            if(o.location){
                position = new TMap.LatLng(o.location.lat,o.location.lng)
            }
            return {
                ...o,
                position
            };
        }).filter(o=>(!isEmpty(o.position)))||[];
    }

    /**
     * 更新对id的数据，如果之前不存在于集合中，会作为新的点标注添加到集合中；
     * @param geometries
     */
    updateMarkerLayer(geometries=[]){
        if(this.markerLayer&&!isEmpty(geometries)){
            this.markerLayer.updateGeometries(this.getNewGeometries(geometries));
        }
    }


    /**
     * 过滤标注信息
     * @param geometries
     * @returns {Array|*[]}
     */
    getNewGeometries(geometries){
        return map(geometries,o=>{
            let position = {};
            if(o.location){
                position = new TMap.LatLng(o.location.lat,o.location.lng)
            }
            return {
                ...o,
                position
            };
        })||[];
    }


    getGeometries(){
        let tList = [];

        return false;
    }

    /**
     * 清空地图所有点标记
     */
    clearMarkerLayer(){
        if(this.markerLayer){
            this.markerLayer.setGeometries([]);
        }
    }

    /**
     * 删除标记
     * @param ids
     */
    deleteMarkerLayer(ids = []){
        if(this.markerLayer&&!isEmpty(ids)){
            this.markerLayer.remove(ids);
        }
    }




    render(){
        let mapStyle = {
            width:'100%',
            height:'100%',
            ...this.props.mapStyle
        };
        return (
            <div id={`container`} className={styles.mapContainer} style={mapStyle}>

            </div>
        );
    }

}
